﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FileParser;
using System.IO;

namespace FileParser
{
    /// <summary>
    /// The C_Storage class deals with saving and reading
    /// Green Evolution Ninja Monkey Animation (.GENMA)
    /// files to save time querying the SVN for information
    /// (which takes a long time). It converts from a two-d
    /// array of C_DataStructure to hard drive and back.
    /// </summary>
    class C_Storage
    {
        /// <summary>
        /// This is an overloaded function for savetofile, which
        /// represents the entirety of a project. This can allow
        /// for partial saves during the process for especially large
        /// files.
        /// </summary>
        /// <param name="info">
        /// Info is the 2D array of datastructures representing the
        /// project, with one axis being revisions and the other being
        /// all the classes in a revision. Note that this array may
        /// be ragged.
        /// </param>
        /// <param name="location">
        /// </param>
        /// <returns>
        /// A boolean representing the sucess of the save. True=success.
        /// </returns>
        public static bool SaveToFile(C_DataStructure[][] info, string location)
        {
            return SaveToFile(info, location, info.Length);
        }

        /// <summary>
        /// This is an overloaded constructor for saving a project
        /// only up to a certain point in the project array. This
        /// is useful for constantly storing a project as it is downloaded
        /// to ward against connection loss.
        /// </summary>
        /// <param name="info">
        /// Info is the 2D array of datastructures representing the
        /// project, with one axis being revisions and the other being
        /// all the classes in a revision. Note that this array may
        /// be ragged.
        /// </param>
        /// <param name="location">
        /// Location is the filename to store to, ending in GENMA. It is
        /// stored in plaintext.
        /// </param>
        /// <param name="saveto">
        /// This is the number to storeto. If saveto is equal to the length
        /// of the project, the entirety of the project will be saved.
        /// </param>
        /// <returns>
        /// A boolean representing the success of the saving. True = success.
        /// </returns>
        public static bool SaveToFile(C_DataStructure[][] info, string location, int saveto)
        {
            FileInfo t = new FileInfo(location);

            StreamWriter Twriter = null;

            try
            {
                Twriter = t.CreateText();

                Twriter.WriteLine(saveto);


                //This handles revision zero
                Twriter.WriteLine("1");
                Twriter.WriteLine("Revision Zero");
                Twriter.WriteLine("rev_0");
                Twriter.WriteLine("none");
                Twriter.WriteLine("0");
                Twriter.WriteLine("0");

                //Remember revs start at 1!
                for (int i = 1; i < saveto; i++)
                {
                    C_DataStructure[] revd = info[i];

                    Twriter.WriteLine(revd.Length);

                    foreach (C_DataStructure dat in revd)
                    {
                        Twriter.WriteLine(dat.GetName());
                        Twriter.WriteLine(dat.GetRefId());
                        Twriter.WriteLine(dat.GetInheritance());
                        
                        Twriter.WriteLine(dat.GetNumVariables());

                        foreach (string s in dat.GetVariables())
                            Twriter.WriteLine(s);

                        Twriter.WriteLine(dat.GetNumFunctions());

                        foreach (string s in dat.GetFunctions())
                            Twriter.WriteLine(s);
                    }
                }

                Twriter.Write(Twriter.NewLine);
            }
            catch(Exception e)
            {
                System.Diagnostics.Debug.WriteLine("Caught an error in  storage: " + e);
                return false;
            }
            finally
            {
                Twriter.Close();
            }

            return true;
        }

        /// <summary>
        /// This is the retrieving functionality of the storage, it
        /// takes .GENMA files and converts them to a filled array
        /// of project datastructures.
        /// </summary>
        /// <param name="location">
        /// The location of the .GENMA file to read. Note that
        /// it does not need to be a .GENMA file if the file is
        /// correctly formatted.
        /// </param>
        /// <returns>
        /// Null if the operation was a failure of their was no data
        /// to recover. Otherwise returns a filled 2D array of
        /// datastructures, representing a project over time.
        /// </returns>
        public static C_DataStructure[][] LoadFromFile(string location)
        {
            StreamReader reader = new StreamReader(location);

            C_DataStructure[][] ret = null;

            try
            {
                int totalrevs = int.Parse( reader.ReadLine() ) ;// first # is total revs

                //System.diagnostics.Debug.WriteLine("Reading:: Number of Revisions - " + totalrevs);

                ret = new C_DataStructure[totalrevs][];

                for (int i = 0; i < totalrevs; i++)
                {
                    int classes = int.Parse(reader.ReadLine());

                    //System.diagnostics.Debug.WriteLine("    Rev(" + i + ") - Classes: " + classes);

                    ret[i] = new C_DataStructure[classes];

                    for (int j = 0; j < classes; j++)
                    {
                        string name = reader.ReadLine();
                        string refer = reader.ReadLine();
                        string inheir = reader.ReadLine();

                        //System.diagnostics.Debug.WriteLine("    Rev(" + i + ") - name/refer/inheir: " + name + " " + refer + " " + inheir);

                        int varcount = int.Parse(reader.ReadLine());

                        //System.diagnostics.Debug.WriteLine("    Rev(" + i + ") - Vars: " + varcount);

                        string[] vars = new string[varcount];

                        for (int k = 0; k < varcount; k++)
                            vars[k] = reader.ReadLine();

                        int functcount = int.Parse(reader.ReadLine());

                        //System.diagnostics.Debug.WriteLine("    Rev(" + i + ") - Functions: " + functcount);

                        string[] functs = new string[functcount];

                        for (int k = 0; k < functcount; k++)
                            functs[k] = reader.ReadLine();

                        ret[i][j] = new C_DataStructure(name, refer, inheir, vars, functs);
                    }
                }
            }
            catch
            {
                System.Diagnostics.Debug.WriteLine("Loader Failed");
                return null;
                //TODO - Some error or another
            }

            finally
            {
                reader.Close();
            }

            return ret;
        }
    }
}
